{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "b3a4e90a-2a39-4617-8664-682c312afc0b",
   "metadata": {},
   "outputs": [],
   "source": [
    "from dotenv import load_dotenv\n",
    "from ast import literal_eval"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "6d5f86b5-a7d9-4f85-8c68-8558711f1cfc",
   "metadata": {},
   "outputs": [],
   "source": [
    "assert load_dotenv()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "4a0df460-01e2-4973-9c22-47d9d4c2bc98",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/tmp/ipykernel_2690831/2518516040.py:3: LangChainDeprecationWarning: The class `TavilySearchResults` was deprecated in LangChain 0.3.25 and will be removed in 1.0. An updated version of the class exists in the :class:`~langchain-tavily package and should be used instead. To use it run `pip install -U :class:`~langchain-tavily` and import as `from :class:`~langchain_tavily import TavilySearch``.\n",
      "  tools = [TavilySearchResults(max_results=3)]\n"
     ]
    }
   ],
   "source": [
    "from langchain_community.tools.tavily_search import TavilySearchResults\n",
    "\n",
    "tools = [TavilySearchResults(max_results=3)]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "9613177b-3b51-4328-aab2-3964f4f92516",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_openai import ChatOpenAI\n",
    "\n",
    "from langgraph.prebuilt import create_react_agent\n",
    "\n",
    "# Choose the LLM that will drive the agent\n",
    "llm = ChatOpenAI(model=\"gpt-4.1-nano\")\n",
    "prompt = \"You are a helpful assistant.\"\n",
    "agent_executor = create_react_agent(llm, tools, prompt=prompt)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "e045631f-f825-4335-88f4-20c698f973f5",
   "metadata": {},
   "outputs": [],
   "source": [
    "messages = agent_executor.invoke({\"messages\": [(\"user\", \"who is the winnner of the us open\")]})['messages']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "cf01ea07-219a-4862-ba75-7c99701cbe81",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "human\n",
      "ai\n",
      "tool\n",
      "ai\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "\"The winner of the most recent US Open in men's singles is Jannik Sinner from Italy, and in women's singles, Aryna Sabalenka.\""
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "for msg in messages:\n",
    "    print(msg.type, )\n",
    "messages[-1].content"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "4ebd7e7a-fd44-4ce4-af79-3bb794d55989",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "In the doubles events, Sam Stosur and Shuai Zhang won the women's title, while Rajeev Ram and Joe Salisbury claimed the men's crown. Salisbury also teamed with Desirae Krawczyk and to win the mixed. [...] In 2016, the US Open once again earned its reputation as the toughest two weeks in tennis. From its concrete surface to the weather that alternates between summer and fall, a Flushing fortnight is not for the faint of heart. So it seemed only fitting that two of the game’s most tenacious competitors, Angelique Kerber and Stan Wawrinka, emerged as its champions. [...] championship. Also with the victories, Williams and Nadal each took home a record payday of $3.6 million as the US Open and Emirates Airline US Open Series champions. The US Open year of the veteran extended to doubles as well, where 40-year-old Leander Paes won the men’s doubles title with 34-year-old Radek Stepanek, and 36-year-old Max Mirnyi teamed with relative youngster Andrea Hlavackova, 27, to claim the mixed championship. Hlavackova also won the women’s doubles title, with 28-year-old\n"
     ]
    }
   ],
   "source": [
    "print(literal_eval(messages[2].content)[0]['content'])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d7fd15ea-3486-4af4-84ef-e27c34c63a95",
   "metadata": {},
   "source": [
    "### State"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "ae060734-95fb-4ecd-af90-0f421dfd32b0",
   "metadata": {},
   "outputs": [],
   "source": [
    "import operator\n",
    "from typing import Annotated, List, Tuple\n",
    "from typing_extensions import TypedDict\n",
    "\n",
    "\n",
    "class PlanExecute(TypedDict):\n",
    "    input: str\n",
    "    plan: List[str]\n",
    "    past_steps: Annotated[List[Tuple], operator.add]\n",
    "    response: str"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "08fb1971-d83e-48d9-9b13-4bc8bf57106b",
   "metadata": {},
   "source": [
    "### planner"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "01e90017-9d12-4883-8d89-e6367eb1cbcd",
   "metadata": {},
   "outputs": [],
   "source": [
    "from pydantic import BaseModel, Field\n",
    "\n",
    "\n",
    "class Plan(BaseModel):\n",
    "    \"\"\"Plan to follow in future\"\"\"\n",
    "\n",
    "    steps: List[str] = Field(\n",
    "        description=\"different steps to follow, should be in sorted order\"\n",
    "    )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "cd30695d-32b9-4ef7-b1df-70ebdd880ec2",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_core.prompts import ChatPromptTemplate\n",
    "\n",
    "planner_prompt = ChatPromptTemplate.from_messages(\n",
    "    [\n",
    "        (\n",
    "            \"system\",\n",
    "            \"\"\"For the given objective, come up with a simple step by step plan. \\\n",
    "This plan should involve individual tasks, that if executed correctly will yield the correct answer. Do not add any superfluous steps. \\\n",
    "The result of the final step should be the final answer. Make sure that each step has all the information needed - do not skip steps.\"\"\",\n",
    "        ),\n",
    "        (\"placeholder\", \"{messages}\"),\n",
    "    ]\n",
    ")\n",
    "planner = planner_prompt | ChatOpenAI(\n",
    "    model=\"gpt-4.1\", temperature=0\n",
    ").with_structured_output(Plan)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "eaa2c43e-2b45-4634-b6d2-6bfc13f1dd2a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Plan(steps=['Identify the current Australian Open winner (the most recent winner of the tournament).', 'Find the full name of the winner.', 'Look up the hometown or place of birth of the winner.', 'The result from the previous step is the answer.'])"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "planner.invoke(\n",
    "    {\n",
    "        \"messages\": [\n",
    "            (\"user\", \"what is the hometown of the current Australia open winner?\")\n",
    "        ]\n",
    "    }\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "283a62ea-08aa-44f0-814b-8a259a0ac717",
   "metadata": {},
   "source": [
    "### Re-Plan Step"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "44b0e23f-2606-4cf4-8168-1172930e7e37",
   "metadata": {},
   "source": [
    "- 注意 re-plan 的 context"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "fdd94b64-9b14-4f79-a0c6-0df00febe7b3",
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import Union\n",
    "\n",
    "\n",
    "class Response(BaseModel):\n",
    "    \"\"\"Response to user.\"\"\"\n",
    "\n",
    "    response: str\n",
    "\n",
    "\n",
    "class Act(BaseModel):\n",
    "    \"\"\"Action to perform.\"\"\"\n",
    "\n",
    "    action: Union[Response, Plan] = Field(\n",
    "        description=\"Action to perform. If you want to respond to user, use Response. \"\n",
    "        \"If you need to further use tools to get the answer, use Plan.\"\n",
    "    )\n",
    "\n",
    "\n",
    "replanner_prompt = ChatPromptTemplate.from_template(\n",
    "    \"\"\"For the given objective, come up with a simple step by step plan. \\\n",
    "This plan should involve individual tasks, that if executed correctly will yield the correct answer. Do not add any superfluous steps. \\\n",
    "The result of the final step should be the final answer. Make sure that each step has all the information needed - do not skip steps.\n",
    "\n",
    "Your objective was this:\n",
    "{input}\n",
    "\n",
    "Your original plan was this:\n",
    "{plan}\n",
    "\n",
    "You have currently done the follow steps:\n",
    "{past_steps}\n",
    "\n",
    "Update your plan accordingly. If no more steps are needed and you can return to the user, then respond with that. Otherwise, fill out the plan. Only add steps to the plan that still NEED to be done. Do not return previously done steps as part of the plan.\"\"\"\n",
    ")\n",
    "\n",
    "\n",
    "replanner = replanner_prompt | ChatOpenAI(\n",
    "    model=\"gpt-4o\", temperature=0\n",
    ").with_structured_output(Act)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "36738654-19c2-4dc4-8a5d-1df8e04f3b1d",
   "metadata": {},
   "source": [
    "### Graph"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "e5ded958-f05a-4e29-8734-ab0abb478835",
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import Literal\n",
    "from langgraph.graph import END\n",
    "\n",
    "\n",
    "async def execute_step(state: PlanExecute):\n",
    "    plan = state[\"plan\"]\n",
    "    plan_str = \"\\n\".join(f\"{i+1}. {step}\" for i, step in enumerate(plan))\n",
    "    task = plan[0]\n",
    "    task_formatted = f\"\"\"For the following plan:\n",
    "{plan_str}\\n\\nYou are tasked with executing step {1}, {task}.\"\"\"\n",
    "    agent_response = await agent_executor.ainvoke(\n",
    "        {\"messages\": [(\"user\", task_formatted)]}\n",
    "    )\n",
    "    return {\n",
    "        \"past_steps\": [(task, agent_response[\"messages\"][-1].content)],\n",
    "    }\n",
    "\n",
    "\n",
    "async def plan_step(state: PlanExecute):\n",
    "    plan = await planner.ainvoke({\"messages\": [(\"user\", state[\"input\"])]})\n",
    "    return {\"plan\": plan.steps}\n",
    "\n",
    "\n",
    "async def replan_step(state: PlanExecute):\n",
    "    output = await replanner.ainvoke(state)\n",
    "    if isinstance(output.action, Response):\n",
    "        return {\"response\": output.action.response}\n",
    "    else:\n",
    "        # 替换新的 plan\n",
    "        return {\"plan\": output.action.steps}\n",
    "\n",
    "\n",
    "def should_end(state: PlanExecute):\n",
    "    if \"response\" in state and state[\"response\"]:\n",
    "        return END\n",
    "    else:\n",
    "        return \"agent\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "f4d990dc-8225-48ee-a1a9-05c8952d8737",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langgraph.graph import StateGraph, START\n",
    "\n",
    "workflow = StateGraph(PlanExecute)\n",
    "\n",
    "# Add the plan node\n",
    "workflow.add_node(\"planner\", plan_step)\n",
    "\n",
    "# Add the execution step\n",
    "workflow.add_node(\"agent\", execute_step)\n",
    "\n",
    "# Add a replan node\n",
    "workflow.add_node(\"replan\", replan_step)\n",
    "\n",
    "workflow.add_edge(START, \"planner\")\n",
    "\n",
    "# From plan we go to agent\n",
    "workflow.add_edge(\"planner\", \"agent\")\n",
    "\n",
    "# From agent, we replan\n",
    "workflow.add_edge(\"agent\", \"replan\")\n",
    "\n",
    "workflow.add_conditional_edges(\n",
    "    \"replan\",\n",
    "    # Next, we pass in the function that will determine which node is called next.\n",
    "    should_end,\n",
    "    [\"agent\", END],\n",
    ")\n",
    "\n",
    "# Finally, we compile it!\n",
    "# This compiles it into a LangChain Runnable,\n",
    "# meaning you can use it as you would any other runnable\n",
    "app = workflow.compile()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "601a914d-12ed-469b-8237-63863f35f082",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from IPython.display import Image, display\n",
    "\n",
    "display(Image(app.get_graph(xray=True).draw_mermaid_png()))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "8f4ec744-67db-42ed-ade3-6181082000d1",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'plan': [\"Identify the winner of the men's 2024 Australian Open.\", 'Find the hometown of the identified winner.', 'The result from step 2 is the final answer.']}\n",
      "{'past_steps': [(\"Identify the winner of the men's 2024 Australian Open.\", \"The winner of the men's 2024 Australian Open is Jannik Sinner.\")]}\n",
      "{'plan': [\"Find the hometown of Jannik Sinner, the winner of the men's 2024 Australian Open.\", 'The result from step 1 is the final answer.']}\n",
      "{'past_steps': [(\"Find the hometown of Jannik Sinner, the winner of the men's 2024 Australian Open.\", 'The hometown of Jannik Sinner is Sexten, which is in the region of South Tyrol in Northern Italy.')]}\n",
      "{'response': \"The objective has been successfully completed. The hometown of Jannik Sinner, the winner of the men's 2024 Australian Open, is Sexten, located in the region of South Tyrol in Northern Italy. No further steps are needed.\"}\n"
     ]
    }
   ],
   "source": [
    "config = {\"recursion_limit\": 50}\n",
    "inputs = {\"input\": \"what is the hometown of the mens 2024 Australia open winner?\"}\n",
    "async for event in app.astream(inputs, config=config):\n",
    "    for k, v in event.items():\n",
    "        if k != \"__end__\":\n",
    "            print(v)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fccbd572-bcfe-46d1-a3ea-3225cce43323",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
